/*
 * FileExtensionFilter.java
 */

package xq.util;

import java.io.File;
import java.io.FilenameFilter;
import java.util.regex.Pattern;
import javax.swing.filechooser.FileFilter;

/**
 * A filter for files having extensions that match a supplied regular
 * expression. For the purposes of this filter, a file extension is defined as
 * one or more characters that follow the last '.' character in the file name,
 * assuming that the last '.' character does not come at the beginning or end
 * of the file name.
 * <p><b>Example:</b></p>
 * <pre>
 *    new FileExtensionFilter("(?i)zip|jar", true, "Classpath Entry");
 * </pre>
 * In the above example, the filter will match any of the following files:
 * <pre>
 *    tools.jar
 *    src.zip
 *    resources.ZiP
 *    mylibs.JAR
 *    someDirectory/
 *    anotherDirectory/
 * </pre>
 * It will not match any of the following:
 * <pre>
 *    .zip
 *    tools.jar.backup
 *    classes.jar.
 *    myjar
 * </pre>
 * @author ThorntonRP
 */
public class FileExtensionFilter extends FileFilter implements java.io.FileFilter, FilenameFilter {

	private final Pattern extensionPattern;
	private final boolean acceptDirectories;
	private final String description;

	public FileExtensionFilter(String extensionRegex) {
		this(extensionRegex, false, extensionRegex);
	}

	public FileExtensionFilter(String extensionRegex, boolean acceptDirectories) {
		this(extensionRegex, acceptDirectories, extensionRegex);
	}

	public FileExtensionFilter(String extensionRegex, boolean acceptDirectories, String description) {
		this.extensionPattern = Pattern.compile(extensionRegex);
		this.acceptDirectories = acceptDirectories;
		this.description = description;
	}

	public boolean accept(File dir, String name) {
		boolean accept = false;
		int extensionIndex = name.lastIndexOf('.');
		if (extensionIndex > 0 && extensionIndex + 1 < name.length()) {
			String extension = name.substring(extensionIndex + 1);
			accept = extensionPattern.matcher(extension).matches();
		}
		return accept;
	}

	@Override
	public boolean accept(File pathname) {
		if (pathname.isDirectory()) {
			return acceptDirectories;
		} else {
			return accept(pathname.getParentFile(), pathname.getName());
		}
	}

	@Override
	public String getDescription() {
		return description;
	}
}
